#include "xLine3D.h"
#include "xHardBuffer.h"
#include "xTechnique.h"
#include "xRenderEntry.h"



namespace XE	
{


	const  xString xLine3d::RenderObject_Type ="Line3d";


	xLine3d::xLine3d(const xString& name,xSceneManager* pSceneMrg,UINT VertexCount, const xColor& color, xRenderQueueLevel level)
		:xRenderObject(name,pSceneMrg,level),m_Buffer(NULL),m_vertexDel(NULL)
	{
		//m_VertexVector.resize(VertexCount);


		m_vertexDel = xHardBufferManager::getSingleton().CreateVertexDeclaration();
		if(m_vertexDel==NULL)
		{
			xLogMessager::getSingleton().logMessage("xlind3d create vertex del Fail ");
			throw("xlind3d create vertex del Fail ");
		}

		WORD offset = 0;
		m_vertexDel->AddVertexElement(0,offset,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,0);
	//	m_vertexDel->AddVertexElement(0,offset,D3DDECLTYPE_D3DCOLOR,D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_COLOR,0);
		m_vertexDel->AddEndElement();


		m_vetexHardBuffer=xHardBufferManager::getSingleton().CreateVertexHardBuffer(VertexCount,m_vertexDel->GetVertexSize());

		float* pBuffer=(float*) m_vetexHardBuffer->Lock();
		for(UINT i = 0 ;i<VertexCount;++i)
		{
			*pBuffer++ = i*10.0f; *pBuffer++ = i*10.0f; *pBuffer++ = i*10.0f;
		//	*((DWORD*)pBuffer)=color;  pBuffer++;
			//*pBuffer++ = color.r; *pBuffer++ = color.g; *pBuffer++ = color.b;*pBuffer++ =color.a;
		}
		m_vetexHardBuffer->UnLock();

		m_pMaterial = xMaterialManager::getSingleton().GetByName(name+"_Mateial");
		if(m_pMaterial.isNull())
		{
			m_pMaterial = xMaterialManager::getSingleton().CreateResource(name+"_Mateial","3DLine.xmat");
		}
		if(m_pMaterial.isNull()==false)
		{
			m_pMaterial->GetRenderScheme(0)->SetConstantValue("VertexColor",&color);
		}else
		{
			m_pMaterial = DefaultMaterial;
		}


	}



	UINT xLine3d::GetPrePointSize()
	{
		if(m_vetexHardBuffer.isNull())
			return 0;
		return  m_vetexHardBuffer->GetVertexSize();

	}


	HRESULT xLine3d::RenderCallBack(XRenderSystem* pRender,xCamera* pCamera,xRenderEntry* pEntry,const u32Flags* RenderFlag)
	{

		if(FAILED(pRender->SetVertexBuffer(0,m_vetexHardBuffer.getPointer())))
			return X_FAIL;

		if(FAILED(pRender->SetVertexDeclaration(m_vertexDel)))
			return X_FAIL;

		if(FAILED(pRender->DrawPrimitive(D3DPT_LINELIST,0,m_vetexHardBuffer->GetVertexCount()/2)))
			return X_FAIL;

         return X_OK;
	}


	void xLine3d::_updateRenderQueue(xRenderQueue* pRenderQueue,const xCamera* pCamera)
	{
		if(IsVisual()==false)
			return ;
		xRenderScheme* pRenderScheme =  m_pMaterial->GetRenderSchemeByDistance(10);
		if(pRenderScheme==NULL)
			return  ;

		xRenderEntry* pEntry = pRenderQueue->GetNextRenderEntry();
		pEntry->m_MeshHandle=0;
		pEntry->m_PassIndex = 0;
		pEntry->m_ShaderHandle = pRenderScheme->GetShader()->GetHandle();
		pEntry->m_pRenderScheme = pRenderScheme;
		pEntry->m_SubMeshIndex = 0;
		pEntry->m_pRenderObject = this;
		pEntry->m_TechniqueIndex =pRenderScheme->GetShader()->GetActiveTechniuqeIndex();
		pEntry->m_useData = 0;



	}



	xLine3d::~xLine3d()
	{
		if(m_vertexDel!=NULL)
			xHardBufferManager::getSingleton().DestoryVertexDeclaration(m_vertexDel);

	}


	size_t xLine3d::GetPointCount()
	{
		if(m_vetexHardBuffer.isNull())
			return 0;
		return m_vetexHardBuffer->GetVertexCount();

	}



	void* xLine3d::Lock()
	{
		if(m_vetexHardBuffer.isNull())
			return NULL;
	   m_Buffer = (char*)	m_vetexHardBuffer->Lock();
	   return m_Buffer;

	}

	void xLine3d::unLock()
	{
		m_Buffer=NULL;
		m_vetexHardBuffer->UnLock();

	}

	//------must Lock befer call these fun

	bool xLine3d::SetPoint(UINT index,const xVector3& point)
	{
		if(m_Buffer==NULL||m_vetexHardBuffer.isNull()||index>=m_vetexHardBuffer->GetVertexCount())
			return false;
		float* pos =(float*)(m_Buffer+(index*GetPrePointSize()));
		*pos++ = point.x;
		*pos++ = point.y;
		*pos++ = point.z;
		return true;
	}

	bool xLine3d::SetPoint(UINT index,float x,float y,float z)
	{
		if(m_Buffer==NULL||m_vetexHardBuffer.isNull()||index>=m_vetexHardBuffer->GetVertexCount())
			return false;
		float* pos =(float*)(m_Buffer+(index*GetPrePointSize()));
		*pos++ = x;
		*pos++ = y;
		*pos++ = z;
		return true;
	}

	bool xLine3d::ReSize( UINT PointCount)
	{
		m_vetexHardBuffer.setNull();
		m_vetexHardBuffer=xHardBufferManager::getSingleton().CreateVertexHardBuffer\
			(PointCount,m_vertexDel->GetVertexSize());
		return true;

	}

	bool xLine3d::SetColor( float r,float g,float b,float a)
	{
		return SetColor(xColor(r,g,b,a));
	}

	bool xLine3d::SetColor(xColor& color)
	{	
		if(m_pMaterial.isNull())
			return false;
		 return  m_pMaterial->GetRenderScheme(0)->SetConstantValue("VertexColor",&color);
	}






	//----------------------------------------------------------------------------------
	//
	// line3d Factory
	//-----------------------------------------------------------------------------------


	const  xString  xLine3dFactory::RenderType="Line3d";

	xRenderObject* xLine3dFactory::CreateRenderObject(const  xRenderObjectCreateParameter& para,xSceneManager*pSceneMrg)
	{
		const xLine3DCreateParameter* pPara = static_cast<const xLine3DCreateParameter*>(&para);
		if(pPara==NULL)
			return NULL;
		return 	new  xLine3d(pPara->GetName(),pSceneMrg,pPara->m_PointCount,pPara->m_Color,pPara->m_RenderQueuelevel);
	}



}